package com.just.springbootcache.service;
import com.just.springbootcache.dao.PersonRepository;
import com.just.springbootcache.domain.Person;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * spring boot cache默认以ConcurrentMapCacheManager作为缓存技术
 * 切换其他缓存技术只需要加上其他缓存技术的依赖以及配置
 */
//@CacheConfig(cacheNames = "people") //公用的缓存设置，本示例可以不用，因为下面的方法都定义了value,缓存名
//在用ehcache时要定义好缓存名，每个缓存可以根据业务情况配置自己的缓存参数，否则用的是默认配置
/**
 * 定制节点路径people，默认节点路径是persons
 */
@Transactional
@Service
public class PersonServiceImpl implements PersonService{
    private static final Logger log=LoggerFactory.getLogger(PersonServiceImpl.class);
    @Autowired
    private PersonRepository personRepository;

    /**
     * 缓存新增或更新的数据到缓存，缓存名称为people，数据的key为person的id
     *
     * @CachePut 表明Spring应该将方法的返回值放到缓存中。在方法的调用前并不会 检查缓存，方法始终都会被调用
     */
    @CachePut(value = "people",key = "#person.id.toString()")
    @Override
    public Person save(Person person) {
        Person p=personRepository.save(person);
        log.info("为id、key为："+p.getId()+"的数据做了缓存");
        return p;
    }

    /**
     *  从缓存people中删除key为id的缓存
     */
    @CacheEvict(value = "people",key="#id.toString()")
    @Override
    public void remove(Long id) {
       log.info("删除了id、key为："+id+"的数据缓存");
       personRepository.delete(id);
    }

    /**
     * 将key为person的id的数据缓存到people中
     *
     *   @Cacheable 表明Spring在调用方法之前，首先应该在缓存中查找方法的返回值。如果这个值能够找到，就会返回缓存的值。否则的话，这个方法就会被调用，返回值会放到缓存之中
     */
    @Cacheable(value = "people",key = "#person.id.toString()")
    @Override
    public Person findOne(Person person) {
        Person p=personRepository.findOne(person.getId());
        log.info("为id、key为："+(p==null?"null":p.getId())+"的数据做了缓存");
        return p;
    }

    /**
     *  condition 在某些条件下才缓存，SpEL表达式编写
     *  与之相反的是unless,在这里就不测试啦
     */
    @Cacheable(value = "people",key = "#id.toString()",condition = "#id lt 10")
    @Override
    public Person conditionFindById(Long id) {
        Person p=personRepository.findOne(id);
        log.info("当id<10的时候才做缓存，而本次查询的数据id为："+id);
        return p;
    }

    /**
     * allEntries=true删除所有缓存
     *  beforeInvocation=true在方法执行之前
     */
    @CacheEvict(value = "people",allEntries = true,beforeInvocation = true)
    @Override
    public void removeAll() {
        personRepository.deleteAll();
    }
}
